package chaincode

import (
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric-chaincode-go/shim"
	"github.com/hyperledger/fabric-protos-go/peer"
)

type SmartContract struct{}

// 初始化
func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) peer.Response {
	return shim.Success(nil)
}

// Invoke 入口函数
func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	function, args := stub.GetFunctionAndParameters()
	switch function {
	case "CreateAsset":
		return s.CreateAsset(stub, args)
	case "QueryAsset":
		return s.QueryAsset(stub, args)
	case "TransferAsset":
		return s.TransferAsset(stub, args)
	default:
		return shim.Error("无效的方法名")
	}
}

// 资产定义
type Asset struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Info  string `json:"info"`
	Owner string `json:"owner"`
}

// 创建资产
func (s *SmartContract) CreateAsset(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	// 参数校验
	if len(args) != 4 {
		return shim.Error("参数数量不正确，需要: ID, 名称, 信息, 所有者")
	}

	// 检查资产是否已存在
	if asset, _ := stub.GetState(args[0]); asset != nil {
		return shim.Error(fmt.Sprintf("资产已存在: %s", args[0]))
	}

	// 创建资产对象
	asset := Asset{
		ID:    args[0],
		Name:  args[1],
		Info:  args[2],
		Owner: args[3],
	}

	// 序列化为JSON
	assetJSON, err := json.Marshal(asset)
	if err != nil {
		return shim.Error(fmt.Sprintf("序列化失败: %s", err.Error()))
	}

	// 存入区块链账本
	if err := stub.PutState(args[0], assetJSON); err != nil {
		return shim.Error(fmt.Sprintf("保存资产失败: %s", err.Error()))
	}

	return shim.Success(nil)
}

// 查询资产
func (s *SmartContract) QueryAsset(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	// 参数校验
	if len(args) != 1 {
		return shim.Error("需要提供资产ID作为参数")
	}

	// 查询资产
	assetJSON, err := stub.GetState(args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("查询失败: %s", err.Error()))
	}
	if assetJSON == nil {
		return shim.Error(fmt.Sprintf("资产不存在: %s", args[0]))
	}

	return shim.Success(assetJSON)
}

// 转移资产
func (s *SmartContract) TransferAsset(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	// 参数校验
	if len(args) != 2 {
		return shim.Error("需要提供资产ID和新所有者作为参数")
	}

	// 查询资产
	assetJSON, err := stub.GetState(args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("查询失败: %s", err.Error()))
	}
	if assetJSON == nil {
		return shim.Error(fmt.Sprintf("资产不存在: %s", args[0]))
	}

	// 反序列化
	var asset Asset
	if err := json.Unmarshal(assetJSON, &asset); err != nil {
		return shim.Error(fmt.Sprintf("反序列化失败: %s", err.Error()))
	}

	// 更新所有者
	asset.Owner = args[1]

	// 序列化更新后的资产
	updatedAssetJSON, err := json.Marshal(asset)
	if err != nil {
		return shim.Error(fmt.Sprintf("序列化失败: %s", err.Error()))
	}

	// 更新账本
	if err := stub.PutState(args[0], updatedAssetJSON); err != nil {
		return shim.Error(fmt.Sprintf("更新资产失败: %s", err.Error()))
	}

	return shim.Success(nil)
}
